﻿using System;
using System.Collections.Generic;
using System.Data;

namespace BizElements.Core
{
    /// <summary>Record transformer factory creates <see cref="IRecordTransformer"/> objects for provided entities. You may register custom tansformers.</summary>
    /// <remarks><para>By default, the factory checks if an entity implements <see cref="IRecordTransformer"/> interface, i.e. if it can service itself. 
    /// If not then a default or custom <see cref="IRecordTransformer"/> object is created that manages entity transformations.</para></remarks>
    public static class RecordTransformerFactory
    {
        static readonly Type DefaultRecordTransformerClass = typeof(RecordTransformer);
        static readonly Dictionary<string, Type> TransformerMap = new Dictionary<string, Type>();

        /// <summary>Registers custom transformer for entities mapped to the specified table/view name.</summary>
        /// <typeparam name="T">A class that implements <see cref="IRecordTransformer"/> interface and has a default/parameterless constructor.</typeparam>
        /// <param name="tableName">Table/view name.</param>
        public static void RegisterTransformer<T>(string tableName)
            where T : class, IRecordTransformer, new()
        {
            TransformerMap[tableName] = typeof(T);
        }

        /// <summary>Gets transformer object that provides transformation services for the specified entity.</summary>
        /// <param name="entity">Entity. If it implements IRecordTransformer then it is returned by the method.</param>
        /// <returns>Transformer.</returns>
        public static IRecordTransformer GetTransformer(IEntity entity)
        {
            // Entity may handle transformation on its own. E.g. classes which derive from EntityModelBase.
            IRecordTransformer transformer = entity as IRecordTransformer;
            if (transformer != null)
                return transformer;

            Type transformerClass;
            TransformerMap.TryGetValue(entity.Table.TableName, out transformerClass);
            if (transformerClass == null)
                transformerClass = DefaultRecordTransformerClass;

            transformer = (IRecordTransformer)Activator.CreateInstance(transformerClass);
            transformer.TransformedEntity = entity;
            return transformer;
        }
    }
}
